/**
 * 
 */
package fhq.hcmute.edu.vn.security;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.HashMap;

import javax.crypto.Cipher;

/**
 * @author nglehien Nov 17, 2012 - 1:57:28 PM
 */
public class KeyManagement {
	private static KeyManagement instance = null;

	public static KeyManagement getInstance() {
		if (instance == null) {
			instance = new KeyManagement();
		}
		return instance;
	}

	private HashMap<String, PrivateKey> keyManagement;

	public HashMap<String, PrivateKey> getKeyManagement() {
		return keyManagement;
	}

	public void setKeyManagement(HashMap<String, PrivateKey> keyManagement) {
		this.keyManagement = keyManagement;
	}

	public void commit() throws IOException {
		String path = "Key Management";
		File file = new File(path);
		if (!file.exists()) {
			file.mkdir();
		}
		path += "/keyManagement.km";
		FileOutputStream fileOutputStream = new FileOutputStream(new File(path));
		ObjectOutputStream objectOutputStream = new ObjectOutputStream(
				fileOutputStream);
		objectOutputStream.writeObject(keyManagement);
		objectOutputStream.close();
	}

	@SuppressWarnings("unchecked")
	public HashMap<String, PrivateKey> open() throws IOException,
			ClassNotFoundException {
		HashMap<String, PrivateKey> keyManagement = null;
		String path = "Key Management/keyManagement.km";
		File file = new File(path);
		if (file.exists()) {
			FileInputStream fileInputStream = new FileInputStream(
					new File(path));
			ObjectInputStream objectInputStream = new ObjectInputStream(
					fileInputStream);
			keyManagement = (HashMap<String, PrivateKey>) objectInputStream
					.readObject();
			fileInputStream.close();
			objectInputStream.close();
		} else {
			keyManagement = new HashMap<String, PrivateKey>();
		}
		return keyManagement;
	}

	private KeyManagement() {
		try {
			this.keyManagement = open();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	private byte[] encrypt(byte[] inpBytes, PublicKey key) throws Exception {
		Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
		cipher.init(Cipher.ENCRYPT_MODE, key);
		return cipher.doFinal(inpBytes);
	}

	private byte[] decrypt(byte[] inpBytes, PrivateKey key) throws Exception {
		Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
		cipher.init(Cipher.DECRYPT_MODE, key);
		return cipher.doFinal(inpBytes);
	}

	public boolean compare(String phoneIMEI, byte[] encBytes, String data)
			throws Exception {
		byte[] dataBytes = data.getBytes();
		PrivateKey prvk = keyManagement.get(phoneIMEI);
		// byte[] encBytes = encrypt(dataBytes, publicKey);
		byte[] decBytes = decrypt(encBytes, prvk);
		return java.util.Arrays.equals(dataBytes, decBytes);
	}
	public PublicKey generatePairKey(String phoneIMEI) {
		try {
			KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
			kpg.initialize(1024);
			KeyPair kp = kpg.genKeyPair();
			keyManagement.put(phoneIMEI, kp.getPrivate());
			return kp.getPublic();
		} catch (Exception e) {
			System.out.println(e.getMessage());
		}
		return null;
	}

	public PrivateKey getPublicKey(String phoneIMEI) {
		return this.keyManagement.get(phoneIMEI);
	}

	public boolean compare(PublicKey publicKey, byte[] decBytes, String data)
			throws Exception {
		byte[] dataBytes = data.getBytes();
		byte[] encBytes = encrypt(dataBytes, publicKey);
		return java.util.Arrays.equals(encBytes, decBytes);
	}

	public void saveKey(ObjectOutputStream oout, Object key) {
		try {
			oout.writeObject(key);
			oout.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

}
